﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reactive;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text;
using Rxx.Labs.Properties;

namespace Rxx.Labs.Reactive.UI
{
	[DisplayName("Observable Bindings")]
	[Description("Binding UI elements to properties with the Subscription XAML markup extension.")]
	public partial class SubscriptionBindingLab : BaseLab
	{
		public string Scalar
		{
			get
			{
				return Text.Observed;
			}
		}

		public IListSubject<string> SlidingList
		{
			get
			{
				return slidingList;
			}
		}

		public IObservable<long> GrowingList
		{
			get
			{
				return growingList;
			}
		}

		public IObservable<object> RockPaperScissorsCounter
		{
			get
			{
				return rockPaperScissorsCounter;
			}
		}

		public IObservable<string> FormatTextResponse
		{
			get
			{
				return formatTextResponse;
			}
		}

		public ISubject<string, string> FormatText
		{
			get
			{
				var subject = new Subject<string>();

				return Subject.Create(
					Observer.Create<string>(
						value =>
						{
							var text = new StringBuilder(value);

							for (int i = 0; i < text.Length; i++)
							{
								var current = text[i];

								if (Array.Exists(removalCharacters, c => c == current))
								{
									text.Remove(i, 1);
									i--;
								}
							}

							subject.OnNext(text.ToString());

							formatTextResponse.OnNext(
								string.Format(
									System.Globalization.CultureInfo.CurrentCulture,
									Text.SubscriptionBindingLabFormatTextResponse,
									value));
						}),
					subject);
			}
		}

		private static readonly char[] vowels = new[] { 'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U' };
		private static readonly char[] numbers = new[] { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };
		private static readonly char[] removalCharacters = vowels.Concat(numbers).Concat(new[] { ' ' }).ToArray();
		private readonly Subject<string> formatTextResponse = new Subject<string>();
		private readonly Subject<object> rockPaperScissorsCounter = new Subject<object>();
		private readonly Subject<long> growingList = new Subject<long>();
		private readonly ListSubject<string> slidingList = new ListSubject<string>();

		public SubscriptionBindingLab()
		{
			InitializeComponent();
		}

		protected override IEnumerable<IDisposable> Main()
		{
			yield return Observable.Return(Text.Rock).Delay(TimeSpan.FromSeconds(1))
				.Concat(Observable.Return(Text.Paper).Delay(TimeSpan.FromSeconds(1)))
				.Concat(Observable.Return(Text.Scissors).Delay(TimeSpan.FromSeconds(1)))
				.Concat(Observable.Interval(TimeSpan.FromSeconds(1)).Select(value => (object) value))
				.Subscribe(rockPaperScissorsCounter);

			yield return Observable.Interval(TimeSpan.FromSeconds(2))
				.Subscribe(growingList);

			yield return Observable.Interval(TimeSpan.FromSeconds(.5))
				.Subscribe(i => slidingList.Add(i.ToString()));

			yield return Observable.Interval(TimeSpan.FromSeconds(.5)).Delay(TimeSpan.FromSeconds(2.5))
				.Subscribe(i => slidingList.Remove(i.ToString()));
		}
	}
}